package com.smart.manager.system.repository;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.smart.common.entities.constant.ExceptionTips;
import com.smart.common.entities.constant.SmartConstant;
import com.smart.common.entities.option.SelectOption;
import com.smart.common.entities.option.TreeOption;
import com.smart.common.exception.SmartException;
import com.smart.manager.system.entities.body.RSystemOrgan;
import com.smart.manager.system.entities.enums.OrganQuality;
import com.smart.manager.system.entities.models.SystemOrgan;
import com.smart.manager.system.entities.models.query.QSystemOrgan;
import io.ebean.DB;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 部门管理- 数据仓库
 *
 * @author xiaxuqiu
 * @date 2022/11/18
 */
@Service
@Log4j2
@RequiredArgsConstructor
public class OrganRepository {


    public List<SystemOrgan> getFullList() {
        return new QSystemOrgan().order().sort.asc().findList();
    }


    /**
     * 修改数据
     *
     * @param id   id
     * @param data 修改后的数据
     */
    public void update(Long id, RSystemOrgan.EditBody data) {
        SystemOrgan record = new QSystemOrgan().id.eq(id).setMaxRows(1).findOne();
        Assert.notNull(record, ExceptionTips.NOT_FOUND);
        BeanUtil.copyProperties(data, record);
        Objects.requireNonNull(record).update();
        updateOrganFullName();
    }

    public int deleteByIds(List<Long> ids) {
        List<SystemOrgan> list = new QSystemOrgan().id.in(ids).findList();


        list.forEach(item -> {

            int childrenCount = this.getChildrenCount(item.getCode());
            if (childrenCount > 0) {
                throw new SmartException(ExceptionTips.HAS_CHILDREN_DATA);
            }

            //TODO 删除部门检查账号
            //TODO 删除部门检查人员档案
        });
        return DB.deleteAll(list);
    }


    private int getChildrenCount(String code) {
        return new QSystemOrgan().parentCode.eq(code).findCount();
    }

    public void add(RSystemOrgan.EditBody data) {
        SystemOrgan record = new QSystemOrgan().code.eq(data.getCode()).setMaxRows(1).findOne();
        Assert.isNull(record, "创建失败:机构代码");
        SystemOrgan systemOrgan = BeanUtil.copyProperties(data, SystemOrgan.class);
        systemOrgan.setQuality(OrganQuality.BRANCH);
        systemOrgan.save();
        updateOrganFullName();
    }


    /**
     * 查询父名字
     *
     * @param allOrgan    所有部门列表
     * @param node        当前部门节点
     * @param currentName 当前部门名称
     * @return {@code StringBuilder}
     */
    protected String getParentName(List<SystemOrgan> allOrgan, SystemOrgan node, String currentName) {

        StringBuilder res = new StringBuilder(currentName);
        for (SystemOrgan dept : allOrgan) {
            if (node.getParentCode().equals(dept.getCode())) {
                res.insert(0, "/");
                res.insert(0, dept.getName());
                if (!SmartConstant.ZERO_STRING.equals(dept.getParentCode())) {
                    res = new StringBuilder(this.getParentName(allOrgan, dept, res.toString()));
                }

            }
        }
        return res.toString();
    }


    /**
     * 更新所有部门的完整名称
     */
    @Async
    protected void updateOrganFullName() {
        List<SystemOrgan> list = new QSystemOrgan().findList();
        for (SystemOrgan dept : list) {
            String fullName = this.getParentName(list, dept, dept.getName());
            dept.setFullName(fullName);
        }
        DB.updateAll(list);
    }


    public List<TreeOption> getTreeOptions() {
        return new QSystemOrgan().order().id.asc().findStream().map(x ->
                new TreeOption(x.getName(), x.getCode(), x.getParentCode())
        ).collect(Collectors.toList());

    }


    public List<SelectOption> getOptions() {
        return new QSystemOrgan().order().id.asc().findStream().map(x ->
                new SelectOption().setValue(x.getCode()).setLabel(x.getName())
        ).collect(Collectors.toList());

    }
}






